package com.ap.core.webservice;

import com.ap.core.business.info.ValidationInfo;
import com.ap.core.cxf.jaxb.common.APCORE1FaultDetailsType;
import com.ap.core.cxf.jaxb.msghdr.MsgHdrType;
import com.ap.core.exception.BusinessFailureException;
import com.ap.core.message.service.MessageProcessor;
import com.ap.core.util.JaxbUtil;
import org.joda.time.LocalDateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.UUID;

/**
 * @author Ranjit.Singh
 * Base Class for exposed Web services
 * @param <REQ> - Type of request parameter
 * @param <RES> - Type of response parameter
 * @param <AI> - Type of additional info
 */
public class BaseWSService<REQ,RES,AI> {

    protected MessageProcessor<REQ, RES, AI> messageProcessor;
    
    private static final String APCORE_TECH_FAULT_ERROR_CODE = "APCORE-99999999";

    /** Logger */
    protected final Logger LOG = LoggerFactory.getLogger(getClass());

    public void setMessageProcessor(MessageProcessor<REQ, RES, AI> messageProcessor) {
        this.messageProcessor = messageProcessor;
    }

    protected String buildMessage(MsgHdrType msgHdrType, BusinessFailureException exception) {
    	StringBuilder stringBuilder = new StringBuilder(150);
        stringBuilder.append("Business Rules failed.\nFailed MessageType is = " + msgHdrType.getMsgType().name() + "\nRequest Message Id is = " + msgHdrType.getMsgId() + "\n");
        int count = 1;
        for(ValidationInfo validationInfo: exception.getErrorCodesInfo()){
            stringBuilder.append(count + ". ErrorCode = " + validationInfo.getInternalBusinessErrorCode() + " and failed rule description is = " + validationInfo.getRuleDescription() + " \n");
            count++;
        }
        String message = stringBuilder.toString();
        LOG.info("Failed with business exception with detail is as = " + message 
        		 +" for Request Message id : = " + msgHdrType.getMsgId() + " at time "+ new LocalDateTime());
        return stringBuilder.toString();
    }
    
    
    protected String getFaultString(String messageType, String msgId){
    	final String serverName = (null != System.getProperty("weblogic.Name") ? System.getProperty("weblogic.Name") : "");
    	final String machineName = (null != System.getProperty("os.hostname") ? System.getProperty("os.hostname") : "");
    	final String faultString = String.format("APCore Fault occurred on Weblogic ServerName:%s & MachineName:%s " +
    			                   " with MessageType:%s and the RequestMessageId:%s \n",serverName, machineName, messageType, msgId);
    	LOG.info("AP Core Fault String:"+faultString);
    	return faultString;
    }                                                                       
    
    /**
     * Build
     * @param messageType
     * @param exception
     * @return
     */
    protected APCORE1FaultDetailsType buildSOAPFaultType(String messageType, String msgId, Exception exception) {
    	LOG.info("APCore Exception Occurred:"+exception.getMessage(), exception);
    	String errorMessage = exception.getMessage();
    	if(null != exception.getMessage() && exception.getMessage().length() > 254){
    		errorMessage = exception.getMessage().substring(0, 254);
    	}
    	final String faultId= UUID.randomUUID().toString();
    	
    	String internalmessage = String.format("APCore Technical Fault occurred with Fault ID:%s  With MessageType:%s " +
    			                               " and the RequestMessageId:%s \n", faultId, messageType,  msgId);
    	final APCORE1FaultDetailsType soapFaultType = constructAPCoreSoapFaultDetails(internalmessage, faultId, 
    			                                       APCORE_TECH_FAULT_ERROR_CODE, errorMessage, APCORE_TECH_FAULT_ERROR_CODE, internalmessage); 
    	LOG.info(buildMessage(internalmessage, msgId, exception, soapFaultType));
    	JaxbUtil.newInstance().javaToXML(APCORE1FaultDetailsType.class, soapFaultType);
    	return soapFaultType;
    }

    
    protected APCORE1FaultDetailsType buildSOAPFaultType(String messageType, String msgId, BusinessFailureException exception) {
    	LOG.info("APCore BusinessFailureException Occurred:"+exception.getMessage(), exception);
		final ValidationInfo validationInfo = exception.getErrorCodesInfo().get(0);
		
		String faultId = String.valueOf(validationInfo.getExceptionDetailsId());
		String internalmessage = String.format("APCore Business Validation Error occurred with Fault ID:%s  With MessageType:%s and the RequestMessageId:%s \n", 
												faultId, messageType,  msgId);
		
		final APCORE1FaultDetailsType soapFaultType =  constructAPCoreSoapFaultDetails(internalmessage, faultId, validationInfo.getExternalBusinessErrorCode(), 
				                                  validationInfo.getExternalBusinessErrorDescription(),	 
				                                  validationInfo.getInternalBusinessErrorCode(), validationInfo.getInternalBusinessErrorDescription());
		
		LOG.info(buildMessage(internalmessage, msgId, exception, soapFaultType));
		JaxbUtil.newInstance().javaToXML(APCORE1FaultDetailsType.class, soapFaultType);
		return soapFaultType;
    }
    
    
    protected String buildMessage(String internalmessage, String msgId, Exception exception, APCORE1FaultDetailsType apCORE1FaultDetails) {
    	StringBuilder stringBuilder = new StringBuilder(150);
    	stringBuilder.append("\n FaultId:"+apCORE1FaultDetails.getFaultid());
    	stringBuilder.append("\n Errorcode:"+apCORE1FaultDetails.getErrorcode()  + " ErrorMessage:"+apCORE1FaultDetails.getErrormessage());
        stringBuilder.append("\n InternalErrorCode:"+apCORE1FaultDetails.getInternalcode() + " InternalErrorMessage:"+apCORE1FaultDetails.getInternalmessage());
        String message = stringBuilder.toString();
        LOG.info("\nFailed with APCore Exception with detail is as = " + message);
        LOG.info("Request Message id : = " + msgId + " at time "+ new LocalDateTime());
        return stringBuilder.toString();
    }

/**
 * @param internalmessage
 * @return
 */
private APCORE1FaultDetailsType constructAPCoreSoapFaultDetails(String internalmessage, String faultId, String errorcode, String errorMessage, 
											String internalCode, String internalMessage) {
		final APCORE1FaultDetailsType apcore1FaultDetails = new APCORE1FaultDetailsType();
		apcore1FaultDetails.setErrorcode(errorcode);
		apcore1FaultDetails.setErrormessage(errorMessage);
		apcore1FaultDetails.setFaultid(faultId);
		apcore1FaultDetails.setInternalcode(internalCode);
		apcore1FaultDetails.setInternalmessage(internalMessage);		
		return apcore1FaultDetails;
}


}
